﻿#region

using System;
using System.Collections.Generic;
using System.Threading;
using MediaSage.Lib;
using MediaSage.Lib.Configuration;
using MediaSage.Lib.Plugin;
using MediaSage.Lib.ThreadManager;
using MediaSage.Lib.Utilities;

#endregion

namespace MediaSageService.ScheduledTasks
{
    public class Scheduler
    {
        #region Fields

        private readonly Config config;
        private readonly Logger logger;
        private readonly IList<Task> tasks;
        private readonly ThreadManager threadManager;
        private bool shutdownScheduler;

        #endregion Fields

        #region Constructors

        public Scheduler(Config Configuration)
        {
            config = Configuration;
            logger = config.Logger;
            tasks = new List<Task>();
            threadManager = config.ThreadManager;
            var schedulerThread = new Thread(ScheduleProcessor);
            schedulerThread.Start();
            logger.Log("MediaSageService.ScheduledTasks.Scheduler initialized");
        }

        ~Scheduler()
        {
            shutdownScheduler = true;
            logger.Log("Shutting down scheduler");
            Thread.Sleep(5000);
        }

        #endregion Constructors

        #region Methods

        private void ScheduleProcessor()
        {
            logger.Log("Entering Scheduler.ScheduleProcessor()");
            while (!shutdownScheduler)
            {
                IList<Guid> ActiveTasks = new List<Guid>();
                foreach (Task task in tasks)
                {
                    if (task.GetNextRunTime().CompareTo(DateTime.Now) <= 0 && task.GetStatus() == Task.Status.Scheduled)
                    {
                        task.SetStatus(Task.Status.Running);                        
                        // Now run the task with the thread manager    
                        Guid threadID = threadManager.CreateMaintenanceThread((PluginBase)task.GetTask());
                        ActiveTasks.Add(threadID);
                    }
                }
                IList<Guid> completeTasks = new List<Guid>();
                foreach (Guid guid in ActiveTasks)
                {
                    bool complete = false;
                    bool canceled = false;
                    Exception e = null;
                    threadManager.GetResult(guid, out complete, out canceled, out e);
                    if (complete)
                    {
                        logger.Log("Maintenance task: " + guid + " complete successfully");
                        completeTasks.Add(guid);
                    }
                    if (canceled)
                    {
                        logger.Log("Maintenance task: " + guid + " canceled");
                        completeTasks.Add(guid);
                    }
                    if (e != null)
                    {
                        logger.Log("Maintenance task: " + guid + " threw exception: " + e.Message);
                        completeTasks.Add(guid);
                    }
                }
                foreach (Guid guid in completeTasks)
                {
                    ActiveTasks.Remove(guid);
                }
                Thread.Sleep(3000);
            }
        }
        
        public void CreateTask(PluginBase provider, DateTime NextRunTime, TimeSpan Interval)
        {
            logger.Log(String.Format("Entering MediaSageService.ScheduledTasks.Scheduler.CreateTask(provider,{0},{1})", arg0: NextRunTime.ToString(), arg1: Interval.ToString()));
            Task task=new Task(config,config.ThreadManager,provider,Interval,NextRunTime);
            tasks.Add(task);
        }

        #endregion Methods
    }
}